﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mimoza.PluginLayer;
using System.Xml.Serialization;
using System.IO;
using Microsoft.Win32;

namespace Mimoza.LocalHostPlugin
{
    class ExecutePlugin : Mimoza.PluginLayer.IExecutePlugin
    {
        #region IExecutePlugin Members

        public string PluginId
        {
            get { return Mimoza.PluginLayer.ExecutePluginManager.LocalHostPluginId; }
        }

        public void Add(Mimoza.ObjectLayer.Policy policy)
        {
            Update(policy);
        }

        public void Remove(Mimoza.ObjectLayer.Policy policy)
        {

        }

        public void Update(Mimoza.ObjectLayer.Policy policy)
        {
            Mimoza.Common.HostRecord hostRecord;
            Mimoza.ObjectLayer.AdapterInfo[] adaptersInfo;
            GetHostRecord(policy, out hostRecord, out adaptersInfo);

            HandleHostName(hostRecord.NewName);
            HandleAdaptersInfo(adaptersInfo);
        }

        #endregion

        void HandleHostName(string hostName)
        {
            string currentHostName = Mimoza.Transport.LocalInfo.HostName;
            if (!string.IsNullOrEmpty(hostName) && currentHostName != hostName)
            {
                Common.Logger.Log.Info("Mimoza.LocalHostPlugin.ExecutePlugin: change host name current - '" + currentHostName +
                    "' new - '" + hostName + "'.");

                bool setRes = SetNewHostName(hostName);

                if (setRes)
                {
                    PluginResultStore.PutRestartResult();
                }
            }
        }

        void HandleAdaptersInfo(Mimoza.ObjectLayer.AdapterInfo[] adaptersInfo)
        {
            if (adaptersInfo==null || adaptersInfo.Length==0) 
                return;

            List<Mimoza.ObjectLayer.AdapterInfo> adaptersList = new List<Mimoza.ObjectLayer.AdapterInfo>(adaptersInfo);

            bool bNeedRestart = false;
            string[] adaptersNames = Transport.LocalInfo.GetAdapters().GetNames();
            for (int i = 0; i < adaptersNames.Length; i++)
            {
                Mimoza.ObjectLayer.AdapterInfo adapterInfo =
                    adaptersList.Find(ai => ai.AdapterID == i);

                if (adapterInfo != null)
                {
                    if (ApplyAdapterInfo(adaptersNames[i], adapterInfo))
                        bNeedRestart = true;
                }
            }

            if (bNeedRestart) PluginResultStore.PutRestartResult();
        }

        bool ApplyAdapterInfo(string adapterName, Mimoza.ObjectLayer.AdapterInfo adapterInfo)
        {
            Mimoza.Common.Instrumental.Registry registry = new Mimoza.Common.Instrumental.Registry(
                "Comm\\" + adapterName + "\\Parms\\Tcpip");

            object intvalue = adapterInfo.EnableDHCP4IP ? 1 : 0;
            registry.CheckAndRewrite("EnableDhcp", intvalue);
            registry.CheckAndRewrite("IPAddress", adapterInfo.IPAddress);
            registry.CheckAndRewrite("SubnetMask", adapterInfo.SubNetMask);
            registry.CheckAndRewrite("DefaultGateway", adapterInfo.DefaultGateWay);
            registry.CheckAndRewrite("DNS", adapterInfo.DNS1);

            return registry.IsModified;
        }

        void GetHostRecord(Mimoza.ObjectLayer.Policy policy, out Mimoza.Common.HostRecord hostRecord,
            out Mimoza.ObjectLayer.AdapterInfo[] adaptersInfo)
        {
            hostRecord = null;
            adaptersInfo = null;

            if (policy.Data!=null)
            {
                XmlSerializer ser = new XmlSerializer(typeof(Common.HostRecord));
                
                StringReader stringStream = new StringReader(policy.Data);

                hostRecord = ser.Deserialize(stringStream) as Common.HostRecord;

                if (hostRecord != null && null != hostRecord.AdaptersInfo)
                {
                    XmlSerializer deserializer = new XmlSerializer(typeof(Mimoza.ObjectLayer.AdapterInfo[]));
                    using (TextReader text = new StringReader(hostRecord.AdaptersInfo))
                    {
                        adaptersInfo = (Mimoza.ObjectLayer.AdapterInfo[])deserializer.Deserialize(text);
                    }
                }
            }

            Trace(hostRecord, adaptersInfo);

            if (hostRecord==null)
            {
                Common.Logger.Log.Error("Mimoza.LocalHostPlugin.ExecutePlugin: wrong format of policy data.");
                throw new ArgumentException();
            }
        }

#if WindowsCE            
        bool SetNewHostName(string hostName)
        {
            Mimoza.Common.Instrumental.Registry registry = new Mimoza.Common.Instrumental.Registry(
                "Ident");

            registry.CheckAndRewrite("Name", hostName);
            
            return registry.IsModified;
        }

        bool SetNewHostName2(string hostName)
        {
            bool bRes = false;

            try
            {
                System.Net.IPHostEntry hostEntry = System.Net.Dns.GetHostEntry("");
                hostEntry.HostName = hostName;
                bRes = true;
            }
            catch (System.Exception e)
            {
                Common.Logger.Log.Error("Mimoza.LocalHostPlugin.ExecutePlugin: can't apply new host name -'" +
                    hostName + "' Error - '" + e.ToString() + "'.");
            }

            return bRes;
        }
#else
        bool SetNewHostName(string hostName)
        {
            return true;
        }
#endif

        void Trace(Mimoza.Common.HostRecord hostRecord,
            Mimoza.ObjectLayer.AdapterInfo[] adaptersInfo)
        {
            if (hostRecord != null)
            {
                Common.Logger.Log.Info("Mimoza.LocalHostPlugin.ExecutePlugin: hostRecord.Name - '{0}'",
                    hostRecord.Name);
            }

            if (adaptersInfo != null)
            {
                Common.Logger.Log.Info("Mimoza.LocalHostPlugin.ExecutePlugin: adaptersInfo.Lenght - {0}",
                    adaptersInfo.Length.ToString());

                Common.Logger.Log.Info("Mimoza.LocalHostPlugin.ExecutePlugin: adaptersInfo:  - {0}",
                    hostRecord.AdaptersInfo);
            }
        
        }
     }
}
